package pair3;

public class PairTest3 {
    public static void main(String[] args) {
        var ceo = new Manager("Gus Greedy", 800000, 2003, 12, 15);
        var cfo = new Manager("Sid Sneaky", 600000, 2003, 12, 15);

        var buddies = new Pair<Employee>(ceo, cfo);
        printBuddies(buddies);

        ceo.setBonus(1000000);
        cfo.setBonus(500000);

        Manager[] managers = {ceo, cfo};
        var result = new Pair<Employee>();

        minmaxBounds(managers, result);
        System.out.println("first: " + result.getFirst().getName()
                    + ", second: " + result.getSecond().getName());

        maxminBonus(managers, result);
        System.out.println("first: " + result.getFirst().getName()
                    + ", second: " + result.getSecond().getName());
    }

    // Pair<? extends Employee>是Pair<Employee>, Pair<Manager>之类的超类
    // 读取时用它， <? extends T> 表示泛型的协变性
    public static void printBuddies(Pair<? extends Employee> p) {
        Employee first = p.getFirst();
        Employee second = p.getSecond();
        System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
    }

    // Pair<? super Manager>是是Pair<Employee>, Pair<Manager>之类的超类
    // 写入时用它, <? super T> 表示泛型的逆变性
    public static void minmaxBounds(Manager[] a, Pair<? super Manager> result) {
        if (a.length == 0) {
            return;
        }
        Manager min = a[0];
        Manager max = a[0];

        for (int i = 1; i < a.length; i++) {
            if (min.getSalary() > a[i].getSalary()) {
                min = a[i];
            }
            if (max.getSalary() < a[i].getSalary()) {
                max = a[i];
            }
        }
        result.setFirst(min);
        result.setSecond(max);
    }

    public static void maxminBonus(Manager[] a, Pair<? super Manager> result) {
        minmaxBounds(a, result);
        ArrayAlg.swapHelper(result);
    }
}

class ArrayAlg {
    public static boolean hasNulls(Pair<?> p) {
        return p.getFirst() == null || p.getSecond() == null;
    }

    public static void swap(Pair<?> p) {
        swapHelper(p);
    }

    // Pair<? super Manager> 作为参数传入时，编译器推导T为Object
    public static <T> void swapHelper(Pair<T> p) {
        T t = p.getFirst();
        p.setFirst(p.getSecond());
        p.setSecond(t);
    }
}

class Pair<T> {
    private T first;
    private T second;

    public Pair() {
        first = null;
        second = null;
    }

    public Pair(T first, T second) {
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return first;
    }

    public T getSecond() {
        return second;
    }

    public void setFirst(T newValue) {
        first = newValue;
    }

    public void setSecond(T newValue) {
        second = newValue;
    }
}
